﻿using System;
using System.Windows;
using System.Threading;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace Genetic
{
    public partial class ResizeWindow
    {
        ResizeInfo resizeInfo = new ResizeInfo();

        private void SetSize(double widthChange, double heightChange, double xChange, double yChange)
        {
            lock (resizeInfo)
            {
                resizeInfo.X = xChange;
                resizeInfo.Y = yChange;
                resizeInfo.Width = widthChange;
                resizeInfo.Height = heightChange;
            }
        }

        private void updateSizeLoop()
        {
            try
            {
                while (resizeInfo.Updating)
                {
                    resizeInfo.Target.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new Action(updateSize));
                    Thread.Sleep(20);
                }
            }
            catch { }
        }

        private void updateSize()
        {
            if (resizeInfo.Target != null)
            {
                double x, y, w, h;
                lock (resizeInfo)
                {
                    x = resizeInfo.Target.Left + resizeInfo.X;
                    y = resizeInfo.Target.Top + resizeInfo.Y;
                    w = resizeInfo.Target.Width + resizeInfo.Width;
                    h = resizeInfo.Target.Height + resizeInfo.Height;
                    resizeInfo.Reset();
                }

                if (w >= resizeInfo.Target.MinWidth && h >= resizeInfo.Target.MinHeight)
                {
                    if (resizeInfo.Target.Left != x)
                        resizeInfo.Target.Left = x;

                    if (resizeInfo.Target.Width != w)
                        resizeInfo.Target.Width = w;

                    if (resizeInfo.Target.Top != y)
                        resizeInfo.Target.Top = y;

                    if (resizeInfo.Target.Height != h)
                        resizeInfo.Target.Height = h;
                }
            }
        }

        void thumb_dragStarted(object sender, DragStartedEventArgs e)
        {
            resizeInfo.Start(((FrameworkElement)sender).TemplatedParent as Window);

            Thread t = new Thread(new ThreadStart(updateSizeLoop))
            {
                IsBackground = true
            };
            t.Start();
        }

        void thumb_dragCompleted(object sender, DragCompletedEventArgs e)
        {
            resizeInfo.Stop();
        }

        private void topLeftThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(-e.HorizontalChange, -e.VerticalChange, e.HorizontalChange, e.VerticalChange);
        }

        private void topRightThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(e.HorizontalChange, -e.VerticalChange, e.HorizontalChange, e.VerticalChange);
        }

        private void bottomLeftThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(-e.HorizontalChange, e.VerticalChange, e.HorizontalChange, 0);
        }

        private void bottomRightThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(e.HorizontalChange, e.VerticalChange, 0, 0);
        }

        private void topThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(0, -e.VerticalChange, 0, e.VerticalChange);
        }

        private void bottomThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(0, e.VerticalChange, 0, 0);
        }

        private void rightThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(e.HorizontalChange, 0, 0, 0);
        }

        private void leftThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            SetSize(-e.HorizontalChange, 0, e.HorizontalChange, 0);
        }

        void SetWindowState(Window window, WindowState state)
        {
            if (window.WindowState == WindowState.Normal)
                window.WindowState = state;
            else
                window.WindowState = WindowState.Normal;
        }

        void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Window window = ((FrameworkElement)sender).TemplatedParent as Window;
            if (window != null)
            {
                if (e.ClickCount == 2)
                    SetWindowState(window, WindowState.Maximized);
                else
                    window.DragMove();
            }
        }

        void WindowClose_Click(object sender, RoutedEventArgs e)
        {
            Window window = ((FrameworkElement)sender).TemplatedParent as Window;
            if (window != null)
                window.Close();
        }

        void WindowMaximize_Click(object sender, RoutedEventArgs e)
        {
            Window window = ((FrameworkElement)sender).TemplatedParent as Window;
            if (window != null)
                SetWindowState(window, WindowState.Maximized);
        }

        void WindowMinimize_Click(object sender, RoutedEventArgs e)
        {
            Window window = ((FrameworkElement)sender).TemplatedParent as Window;
            if (window != null)
                SetWindowState(window, WindowState.Minimized);
        }
    }

    public class ResizeInfo
    {
        public bool Updating { get; set; }
        public Window Target { get; set; }

        public double X { get; set; }
        public double Y { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }

        public void Start(Window target)
        {
            Target = target;
            Updating = true;
        }

        public void Stop()
        {
            Updating = false;
            Target = null;
            Reset();
        }

        public void Reset()
        {
            X = 0;
            Y = 0;
            Width = 0;
            Height = 0;
        }
    }
}
